//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//

package cn.com.jit.assp.ias.sp.saml11;

import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.Timer;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.annotation.WebFilter;
import javax.servlet.annotation.WebInitParam;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import com.example.demo.props.PkiProperties;

import cn.com.jit.assp.ias.http.HttpServerStatusChecker;
import cn.com.jit.assp.ias.principal.UserPrincipal;
import cn.com.jit.assp.ias.saml.saml11.SAMLMessage;
import cn.com.jit.assp.ias.saml.saml11.SAMLUtils;
import cn.com.jit.assp.ias.saml.saml11.SAMLValidityChecker;
import cn.com.jit.assp.ias.sp.saml11.compatible.PrincipalSetterFactory;
import cn.com.jit.assp.ias.sp.saml11.config.AgentConfigException;
import cn.com.jit.assp.ias.sp.saml11.config.Configuration;
import cn.com.jit.assp.ias.sp.saml11.config.XMLConfiguration;
import cn.com.jit.assp.ias.sp.saml11.config.bean.Gateway;
import cn.com.jit.assp.ias.sp.saml11.config.util.GatewayList;
import cn.com.jit.assp.ias.sp.saml11.config.util.GatewayTimerTask;
import cn.com.jit.cinas.commons.i18n.TextBundle;
import cn.com.jit.cinas.commons.jaxp.DocumentBuilderConfigurator;
import cn.com.jit.cinas.commons.jaxp.DocumentBuilderFactoryConfigurator;
import cn.com.jit.cinas.commons.jaxp.DocumentBuilderPool;
import cn.com.jit.cinas.commons.jaxp.JAXPException;
import cn.com.jit.cinas.commons.session.Session;
import cn.com.jit.cinas.commons.session.SessionManagementException;
import cn.com.jit.cinas.commons.util.IoUtils;
import cn.com.jit.cinas.commons.util.RequestUtils;

@WebFilter(filterName = "AccessController", urlPatterns = "/blade-auth/ext/pki/token",
    initParams = {@WebInitParam(name = "SPConfig", value = "config/JITAgentConfig.xml")})
public class AccessController implements Filter {

    private static final Log logger = LogFactory.getLog(AccessController.class);
    protected static final TextBundle bundle = TextBundle.getInstance("cn.com.jit.assp.ias.constant.Errors");
    private ArtifactProcessor artifactProcessor;
    private PrincipalSetter principalSetter;
    private Configuration config;
    private HttpServerStatusChecker checker;
    @Autowired
    private PkiProperties pkiProperties;

    public AccessController() {}

    @Override
    public void destroy() {}

    @Override
    public void doFilter(ServletRequest req, ServletResponse resp, FilterChain chain)
        throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest)req;
        HttpServletResponse response = (HttpServletResponse)resp;
        if (this.checkExcept(request)) {
            logger.debug("request a except url , do not authenticate");
            chain.doFilter(request, response);
        } else if (this.checkSession(request)) {
            if (!this.checkArtifact(request)) {
                if (SPUtil.getUserPrincipal(request) == null) {
                    this.logout(request, response);
                    return;
                }
                logger.debug("check sso session successful");
                chain.doFilter(request, response);
            } else {
                logger.debug("clean artifact");
                response.sendRedirect(SAMLUtils.getClearRequestUrl(request));
            }

        } else {
            if (this.isEnableOffline()) {
                logger.debug("process OffLineStrategy");
                if (this.config.getGatewayList().getUsedGateway() == null) {
                    logger.debug("Set offline flag");
                    if (this.isPermitted()) {
                        this.setOffLineFlag(request);
                        if (!this.checkArtifact(request)) {
                            chain.doFilter(request, response);
                        } else {
                            response.sendRedirect(SAMLUtils.getClearRequestUrl(request));
                        }
                    } else {
                        this.gotoErrorPage(request, response, "MESSAGE_CODE_1300D0B4", "OffLineStrategy", "");
                    }
                    return;
                }

                logger.debug("Clear offline flag");
                this.clearOffLineFlag(request);
            }

            if (this.checkArtifact(request)) {
                logger.debug("process saml artifact");
                this.artifactProcessor.handle(request, response);
            } else {
                logger.info("准备跳转");
                logger.debug("sso session not found , redirect to login");
                this.gotoLogin(request, response);
            }
        }
    }

    public final void logout(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        Cookie[] cos = req.getCookies();

        for (int i = 0; i < cos.length; ++i) {
            if (cos[i].getName().equals("_ias_client_token")) {
                cos[i].setMaxAge(0);
                cos[i].setPath("/");
                resp.addCookie(cos[i]);
            }
        }

        String testURL = this.config.getGatewayList().getUsedGateway().getAvailableTesting();
        String url = SAMLUtils.buildUrlWithTargetAndArtifact(
            "https://" + this.getGatewayIp(testURL) + ":4443/saml11/LoginService?method=logout",
            req.getRequestURL().toString(), (String)null);
        logger.info(" logout url " + url);
        resp.sendRedirect(url);
    }

    private String getGatewayIp(String str) {
        String[] strs = str.split(":");
        return strs[1].substring(2);
    }

    private final boolean checkExcept(HttpServletRequest request) {
        String[] notAuthenticate = this.config.getJ2EEAgentSet().getNotAuthenticate();
        if (notAuthenticate != null && notAuthenticate.length != 0) {
            String uri = RequestUtils.getRequestURI(request);
            if (logger.isDebugEnabled()) {
                logger.debug("client request uri : " + uri);
            }

            for (int i = 0; i < notAuthenticate.length; ++i) {
                String next = notAuthenticate[i];
                if (uri.indexOf(next) == 0) {
                    if (logger.isDebugEnabled()) {
                        logger.debug("match : " + next);
                    }

                    return true;
                }
            }

            return false;
        } else {
            return false;
        }
    }

    private final boolean checkSession(HttpServletRequest request) {
        String sid = SPUtil.getSessionId(request);
        if (sid != null && !sid.trim().equals("")) {
            Session session = null;

            try {
                session = this.config.getSessionManager().getSession(sid);
            } catch (SessionManagementException var5) {
                logger.error("SessionManagerException ! ", var5);
                return false;
            }

            if (session == null) {
                return false;
            } else if (!SAMLValidityChecker.checkValidity((Date)session.getAttribute("_saml_not_before"),
                (Date)session.getAttribute("_saml_not_on_or_after"))) {
                session.invalidate();
                return false;
            } else {
                if (!this.config.isUseSessionScope()) {
                    UserPrincipal p = (UserPrincipal)session.getAttribute("_user_principal");
                    this.principalSetter.setUserPrincipal(request, p);
                }

                return true;
            }
        } else {
            return false;
        }
    }

    private final boolean checkArtifact(HttpServletRequest request) {
        return request.getParameter("SAMLArt") != null;
    }

    private boolean isEnableOffline() {
        return this.config.getAgentSet().getOffLine().isEnable();
    }

    private void clearOffLineFlag(HttpServletRequest req) {
        if (this.config.isUseSessionScope()) {
            req.getSession().removeAttribute("_idp_offline");
        } else {
            req.removeAttribute("_idp_offline");
        }

    }

    private boolean isPermitted() {
        return "Permit".equals(this.config.getAgentSet().getOffLine().getAccessStrategy());
    }

    private void setOffLineFlag(HttpServletRequest req) {
        if (this.config.isUseSessionScope()) {
            req.getSession().setAttribute("_idp_offline", "isOffLine");
        } else {
            req.setAttribute("_idp_offline", "isOffLine");
        }

    }

    private final void gotoErrorPage(HttpServletRequest request, HttpServletResponse response, String code,
        String location, String detail) throws ServletException, IOException {
        SAMLMessage msg = new SAMLMessage();
        msg.setCode(code);
        msg.setMessage(bundle.getText(code));
        msg.setLocation(location);
        msg.setDetail(detail);
        request.setAttribute("_saml_action_error", msg);
        if (logger.isDebugEnabled()) {
            logger.debug("forward to error page : " + this.config.getJ2EEAgentSet().getErrorPage());
        }

        RequestUtils.getRequestDispatcher(request, this.config.getJ2EEAgentSet().getErrorPage()).forward(request,
            response);
    }

    private final void gotoLogin(HttpServletRequest request, HttpServletResponse response)
        throws IOException, ServletException {
        this.clearUserPrincipal(request, response);
        String target = SAMLUtils.getClearRequestUrl(request);
        String url = SAMLUtils.buildUrlWithTargetAndArtifact(
            this.config.getGatewayList().getUsedGateway().getLoginURL(), target, (String)null);
        if (logger.isDebugEnabled()) {
            logger.debug("-----------send redirect to : " + url);
        }

        response.sendRedirect(url);
    }

    private final void clearUserPrincipal(HttpServletRequest request, HttpServletResponse response) {
        if (this.config.isUseSessionScope()) {
            HttpSession ss = request.getSession();
            if (ss != null) {
                ss.removeAttribute(this.config.getJ2EEAgentSet().getUserInfoKeyName());
            }
        }

    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
        InputStream in = null;
        XMLConfiguration cfg = XMLConfiguration.getInstance();
        String spConfig = filterConfig.getInitParameter("SPConfig");
        if (spConfig == null) {
            throw new ServletException("Config file path not be set");
        } else {
            if (logger.isDebugEnabled()) {
                logger.debug("SPConfig path = " + spConfig);
            }

            logger.info("Start initializing AccessController");
            Resource resource = new ClassPathResource(spConfig);
            try {
                in = resource.getInputStream();
            } catch (IOException e) {
                e.printStackTrace();
            }
            // ServletContext ctx = filterConfig.getServletContext();
            // logger.info("Start initializing AccessController");
            // in = ctx.getResourceAsStream(spConfig);

            Document doc = null;

            try {
                doc = DocumentBuilderPool
                    .getInstance((DocumentBuilderFactoryConfigurator)null, (DocumentBuilderConfigurator)null).parse(in);
            } catch (JAXPException var10) {
                var10.printStackTrace();
                logger.error("", var10);
                throw new ServletException(var10);
            } catch (SAXException var11) {
                var11.printStackTrace();
                logger.error(" The XML parser error, please check " + spConfig + " config.", var11);
                throw new ServletException(var11);
            } catch (IOException var12) {
                var12.printStackTrace();
                logger.error("Read " + spConfig + " file error, please check web.xml config.", var12);
                throw new ServletException(var12);
            }

            try {
                cfg.configure(doc, pkiProperties);
            } catch (AgentConfigException var9) {
                var9.printStackTrace();
                logger.error("", var9);
                throw new ServletException(var9);
            }

            this.config = cfg;
            this.artifactProcessor = new ArtifactProcessor();
            this.principalSetter = PrincipalSetterFactory.build();
            if (this.isEnableOffline()) {
                this.checker = new HttpServerStatusChecker(this.config.getAgentSet().getOffLine().getTestPeriod());
                Timer timer = new Timer();
                timer.schedule(new GatewayTimerTask(), 0L,
                    (long)this.config.getAgentSet().getOffLine().getTestPeriod() * 1000L);
                logger.info("GateWay Thread ");
            } else {
                new GatewayList();
                GatewayList gateList = this.config.getGatewayList();
                Gateway g = gateList.get(0);
                g.setAlive(true);
            }

            logger.info("Initialize AccessController complete");
            IoUtils.close(in);
        }
    }
}
